home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
AX25SUBR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-02
|
14KB
|
597 lines
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "ax25.h"
#include "lapb.h"
#include <ctype.h>
struct ax25_cb *ax25_cb[NHASH];
struct ax25_call *ax25_digi[NHASH];
struct ax25_call *ax25_call[NHASH];
struct ax25_call *ax25_excl[NHASH];
struct ax25_call *ax25_port;
/* Default AX.25 parameters */
int16 t1init = SEC2TICK(10); /* FRACK of 10 seconds */
int16 t2init = SEC2TICK(1); /* 1 sec acknowledgment delay */
int16 t3init = 0; /* No keep-alive polling */
int16 t4init = 0; /* No disconnection of idle links */
int16 maxframe = 1; /* Stop and wait */
int16 maxsamml = 0; /* No framesammler */
int16 n2 = 10; /* 10 retries */
int16 axwindow = 2048; /* 2K incoming text before RNR'ing */
int16 paclen = 256; /* 256-byte I fields */
int16 pthresh = 128; /* Send polls for packets larger than this */
/* Address hash function. Exclusive-ORs each byte, ignoring
* such insignificant, annoying things as E and H bits
*/
static
int16
ax25hash(s)
register struct ax25_addr *s;
{
register char x;
x = s->call[0] ^ s->call[1] ^ s->call[2] ^
s->call[3] ^ s->call[4] ^ s->call[5];
x ^= s->ssid & SSID;
return (uchar(x) & 0xfe) % NHASH;
}
/* Look up entry in hash table */
struct ax25_cb *
find_ax25(dest,source)
register struct ax25_addr *dest;
struct ax25_addr *source;
{
int16 hashval;
register struct ax25_cb *axp;
/*int i_state;*/
/* Find appropriate hash chain */
hashval = ax25hash(dest);
/* Search hash chain */
/*i_state = disable();*/
for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
if(addreq(&axp->addr.dest,dest) &&
addreq(&axp->addr.source,source)){
/*restore(i_state);*/
return axp;
}
}
/*restore(i_state);*/
return NULLAX25;
}
/* Remove address entry from hash table */
del_ax25(axp)
register struct ax25_cb *axp;
{
int16 hashval;
int i;
/*int i_state;*/
if(axp == NULLAX25)
return;
/* Remove from hash header list if first on chain */
hashval = ax25hash(&axp->addr.dest);
/*i_state = disable();*/
/* Remove from chain list */
if(ax25_cb[hashval] == axp)
ax25_cb[hashval] = axp->next;
if(axp->prev != NULLAX25)
axp->prev->next = axp->next;
if(axp->next != NULLAX25)
axp->next->prev = axp->prev;
/* Timers should already be stopped, but just in case... */
stop_timer(&axp->t1);
stop_timer(&axp->t2);
stop_timer(&axp->t3);
stop_timer(&axp->t4);
/* Free allocated resources */
free_q(&axp->txq);
free_p(axp->rxasm);
free_q(&axp->rxq);
for(i = 0; i < 8; i++){
free_p(axp->sammlq[i]);
axp->sammlq[i] = NULLBUF;
}
free((char *)axp);
/*restore(i_state);*/
}
/* Create an ax25 control block. Allocate a new structure, if necessary,
* and fill it with all the defaults. The caller
* is still responsible for filling in the reply address
*/
struct ax25_cb *
cr_ax25(dest,source)
struct ax25_addr *dest,*source;
{
void recover(),send_ack(),pollthem(),disc_ax25(),ax_incom();
register struct ax25_cb *axp;
int16 hashval;
/*int i_state;*/
if(dest == NULLAXADDR || source == NULLAXADDR)
return NULLAX25;
if((axp = find_ax25(dest,source)) == NULLAX25){
/* Not already in table; create an entry
* and insert it at the head of the chain
*/
/* Find appropriate hash chain */
hashval = ax25hash(dest);
/*i_state = disable();*/
axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
if(axp == NULLAX25)
return NULLAX25;
/* Insert at beginning of chain */
axp->prev = NULLAX25;
axp->next = ax25_cb[hashval];
if(axp->next != NULLAX25)
axp->next->prev = axp;
ax25_cb[hashval] = axp;
/*restore(i_state);*/
}
axp->maxframe = maxframe;
axp->maxsamml = maxsamml;
axp->window = axwindow;
axp->paclen = paclen;
axp->proto = V2; /* Default, can be changed by other end */
axp->pthresh = pthresh;
axp->n2 = n2;
axp->t1.start = t1init;
axp->t1.func = recover;
axp->t1.arg = (char *)axp;
axp->t2.start = t2init;
axp->t2.func = send_ack;
axp->t2.arg = (char *)axp;
axp->t3.start = t3init;
axp->t3.func = pollthem;
axp->t3.arg = (char *)axp;
axp->t4.start = t4init;
axp->t4.func = disc_ax25;
axp->t4.arg = (char *)axp;
axp->r_upcall = ax_incom;
return axp;
}
/* Look up ax25 callsign entry in hash table (digi, call or excl) */
struct ax25_call *
find_axcall(table,addr)
struct ax25_call *table[];
register struct ax25_addr *addr;
{
int16 hashval;
register struct ax25_call *axp;
/* Find appropriate hash chain */
hashval = ax25hash(addr);
/* Search hash chain */
for(axp = table[hashval]; axp != NULLAXCALL; axp = axp->next){
if(addreq(&axp->addr,addr)){
return axp;
}
}
return NULLAXCALL;
}
/* Remove address entry from hash table (digi, call or excl) */
del_axcall(table,axp)
struct ax25_call *table[];
register struct ax25_call *axp;
{
int16 hashval;
if(axp == NULLAXCALL)
return;
/* Remove from hash header list if first on chain */
hashval = ax25hash(&axp->addr);
/* Remove from chain list */
if(table[hashval] == axp)
table[hashval] = axp->next;
if(axp->prev != NULLAXCALL)
axp->prev->next = axp->next;
if(axp->next != NULLAXCALL)
axp->next->prev = axp->prev;
free((char *) axp);
}
/* Create an ax25 call control block. Allocate a new structure, if necessary,
* and fill it with all the defaults.
*/
struct ax25_call *
cr_axcall(table,addr)
struct ax25_call *table[];
struct ax25_addr *addr;
{
register struct ax25_call *axp;
int16 hashval;
if(addr == NULLAXADDR)
return NULLAXCALL;
if((axp = find_axcall(table,addr)) == NULLAXCALL){
/* Not already in table; create an entry
* and insert it at the head of the chain
*/
/* Find appropriate hash chain */
hashval = ax25hash(addr);
axp = (struct ax25_call *)calloc(1,sizeof(struct ax25_call));
if(axp == NULLAXCALL)
return NULLAXCALL;
ASSIGN(axp->addr,*addr);
/* Insert at beginning of chain */
axp->prev = NULLAXCALL;
axp->next = table[hashval];
if(axp->next != NULLAXCALL)
axp->next->prev = axp;
table[hashval] = axp;
}
return axp;
}
/*
* setcall - convert callsign plus substation ID of the form
* "KA9Q-0" to AX.25 (shifted) address format.
* also converts the source to uppercase (uniform output)
* Address extension bit is set (pe1chl: this seems more convenient)
* Return -1 on error, 0 if OK
*/
int
setcall(out,call)
struct ax25_addr *out;
register char *call;
{
int csize;
unsigned ssid;
register int i;
register char *cp,*dp;
if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
return -1;
}
/* Find dash, if any, separating callsign from ssid
* Then compute length of callsign field and make sure
* it isn't excessive
*/
dp = index(call,'-');
if(dp == NULLCHAR)
csize = strlen(call);
else
csize = (int) (dp - call);
if(csize < 3 || csize > ALEN)
return -1;
/* Now find and convert ssid, if any */
if(dp != NULLCHAR){
dp++; /* skip dash */
ssid = atoi(dp);
if(ssid > 15)
return -1;
} else
ssid = 0;
/* Copy upper-case callsign, left shifted one bit */
cp = out->call;
for(i=0;i<csize;i++){
if(!isascii(*call) || !isalnum(*call))
return -1;
*call = toupper(*call);
*cp++ = *call++ << 1;
}
/* Pad with shifted spaces if necessary */
for(;i<ALEN;i++)
*cp++ = ' ' << 1;
/* Insert substation ID field, set reserved bits and E(extension) */
out->ssid = 0x60 | (ssid << 1) | E;
return 0;
}
/*
* valid_call: validate an address according to AX.25 rules
* return 0 for valid address
*/
int
valid_addr (addr)
struct ax25_addr *addr;
{
register char *cp;
register char c;
int i;
cp = addr->call;
for(i=ALEN;i != 0;i--){
if ((c = (*cp++ >> 1) & 0x7f) == ' ' && i <= (ALEN-3))
continue;
if (!isupper(c) && !isdigit(c))
return -1;
}
return 0;
}
/* Set a digipeater string in an ARP table entry */
setpath(out,in,cnt)
char *out; /* Target char array containing addresses in net form */
char *in[]; /* Input array of tokenized callsigns in